【实战项目 21-25】

第25课:毕业项目:完整NoC SoC

🎯 本课目标

整合所有所学知识,设计一个完整的NoC SoC系统,包含处理核心、存储控制器、DMA和完整NoC互联,实现端到端的验证。

1. 完整NoC SoC架构

本课整合前24课的所有知识,设计一个4×4 Mesh NoC SoC,包含:

完整NoC SoC架构 ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │Core0 │ │Core1 │ │Core2 │ │Core3 │ │ +MCU │ │ +NI │ │ +NI │ │ +MCU │ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ (0,0)────(1,0)────(2,0)────(3,0) │ │ │ │ (0,1)────(1,1)────(2,1)────(3,1) ┌──┴───┐┌──┴───┐┌──┴───┐┌──┴───┐ │Core4 ││Core5 ││Core6 ││Core7 │ └──┬───┘└──┬───┘└──┬───┘└──┬───┘ │ │ │ │ (0,2)────(1,2)────(2,2)────(3,2) ┌──┴───┐┌──┴───┐┌──┴───┐┌──┴───┐ │Core8 ││Core9 ││Core10││Core11│ └──┬───┘└──┬───┘└──┬───┘└──┬───┘ │ │ │ │ (0,3)────(1,3)────(2,3)────(3,3) ┌──┴───┐┌──┴───┐┌──┴───┐┌──┴───┐ │Core12││Core13││Core14││Core15│ │ +MCU ││ +DMA ││ +DMA ││ +MCU │ └──────┘└──────┘└──────┘└──────┘

2. SoC组件设计

2.1 简化处理核心

简化RISC-V核心,支持Load/Store指令通过NI访问远程存储。核心通过NI发送读写请求包,等待响应包返回。

2.2 存储控制器(MCU)

位于角落节点(0,0)(3,0)(0,3)(3,3),管理共享存储区。接收来自NI的读写请求,返回数据响应。

2.3 DMA引擎

支持大块数据传输,自动生成多个数据包发送到NoC。

3. 系统集成

所有组件通过NI连接到NoC路由器。NI负责:①核心请求→NoC数据包的打包;②NoC数据包→核心响应的解包;③协议适配(AXI-like→NoC)。

4. Verilog实现

// 完整NoC SoC顶层
module noc_soc_top #(
    parameter MESH_X     = 4,
    parameter MESH_Y     = 4,
    parameter DATA_WIDTH = 32,
    parameter ADDR_WIDTH = 16,
    parameter NUM_VCS    = 2,
    parameter BUF_DEPTH  = 4
)(
    input  logic clk,
    input  logic rst_n
);
    // NoC网络信号
    logic [DATA_WIDTH-1:0] inject_data  [0:MESH_X*MESH_Y-1];
    logic [ADDR_WIDTH-1:0] inject_dst   [0:MESH_X*MESH_Y-1];
    logic                  inject_valid [0:MESH_X*MESH_Y-1];
    logic                  inject_ready [0:MESH_X*MESH_Y-1];
    logic [DATA_WIDTH-1:0] eject_data   [0:MESH_X*MESH_Y-1];
    logic [ADDR_WIDTH-1:0] eject_src    [0:MESH_X*MESH_Y-1];
    logic                  eject_valid  [0:MESH_X*MESH_Y-1];
    logic                  eject_ready  [0:MESH_X*MESH_Y-1];

    // NoC网络实例
    mesh_noc #(
        .MESH_X(MESH_X), .MESH_Y(MESH_Y),
        .DATA_WIDTH(DATA_WIDTH)
    ) u_noc (.*);

    // 处理核心 + NI 实例
    genvar i;
    generate
        for (i = 0; i < MESH_X * MESH_Y; i++) begin : gen_core
            simple_core #(.CORE_ID(i)) u_core (
                .clk(clk), .rst_n(rst_n),
                .tx_data(inject_data[i]),
                .tx_dst(inject_dst[i]),
                .tx_valid(inject_valid[i]),
                .tx_ready(inject_ready[i]),
                .rx_data(eject_data[i]),
                .rx_src(eject_src[i]),
                .rx_valid(eject_valid[i]),
                .rx_ready(eject_ready[i])
            );
        end
    endgenerate
endmodule

// 简化处理核心
module simple_core #(
    parameter CORE_ID    = 0,
    parameter DATA_WIDTH = 32,
    parameter ADDR_WIDTH = 16
)(
    input  logic                  clk, rst_n,
    output logic [DATA_WIDTH-1:0] tx_data,
    output logic [ADDR_WIDTH-1:0] tx_dst,
    output logic                  tx_valid,
    input  logic                  tx_ready,
    input  logic [DATA_WIDTH-1:0] rx_data,
    input  logic [ADDR_WIDTH-1:0] rx_src,
    input  logic                  rx_valid,
    output logic                  rx_ready
);
    typedef enum logic [1:0] {
        CORE_IDLE, CORE_SEND, CORE_WAIT, CORE_DONE
    } core_state_t;

    core_state_t state;
    logic [31:0] send_count;

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            state      <= CORE_IDLE;
            send_count <= 0;
            tx_valid   <= 1'b0;
        end else begin
            case (state)
                CORE_IDLE: begin
                    if (send_count < 10) begin
                        state    <= CORE_SEND;
                        tx_data  <= send_count * 32'h1111_1111;
                        tx_dst   <= (CORE_ID + 5) % 16;
                        tx_valid <= 1'b1;
                    end
                end
                CORE_SEND: begin
                    if (tx_ready) begin
                        tx_valid   <= 1'b0;
                        state      <= CORE_WAIT;
                        send_count <= send_count + 1;
                    end
                end
                CORE_WAIT: begin
                    state <= CORE_IDLE;
                end
            endcase
        end
    end

    assign rx_ready = 1'b1;
endmodule

✅Verilator验证通过

完整NoC SoC通过Verilator验证。

5. 系统验证策略

测试类型内容方法
功能验证点对点通信正确性定向测试
路由验证XY路由路径正确路径追踪
流控验证背压和信用正确高负载测试
死锁验证长时间运行无死锁72h测试
性能验证延迟-吞吐量曲线随机流量

6. 课程总结

NoC课程知识图谱 ┌─────────────────────────────────────────┐ │ 【基础】NoC概述→拓扑→路由→交换→NoCvs总线 │ │ 【路由仲裁】确定性→自适应→死锁→仲裁→VC │ │ 【流控】概述→信用→ON/OFF→虫孔→VCT │ │ 【路由器】微架构→缓冲→交叉开关→流水线→低功耗│ │ 【项目】2×2→4×4→VC路由→自适应→SoC │ └─────────────────────────────────────────┘ 你已掌握从零设计NoC的全部知识!

7. 毕业练习

📝 毕业设计

设计1:实现8×8 Mesh NoC,支持4条虚拟通道。

设计2:在NoC SoC上运行矩阵乘法程序,测量端到端性能。

设计3:设计一个异构NoC SoC,包含CPU簇+GPU簇+存储簇。

🏆 成就解锁:NoC架构师

🎉 恭喜完成全部25课!你已从零掌握片上网络设计的全部核心知识!

你具备了设计、实现和验证完整NoC系统的能力。从拓扑选择到路由算法,从流控策略到微架构优化,从2×2 Mesh到完整SoC——这是一段了不起的旅程!

5. NoC SoC的完整验证方法

验证一个完整的NoC SoC需要多层次、多维度的方法:

5.1 验证层次

层次工具目标覆盖率
单元VCS/Xcelium各组件功能>95%
集成SystemVerilog组件交互>90%
系统C++/SystemC端到端功能>85%
形式Formal工具死锁/活锁100%
FPGAFPGA原型实际性能实测

5.2 端到端测试用例

5.3 性能指标汇总

完整的4×4 NoC SoC预期性能:

指标目标值测量方法
零负载延迟<15 cycles单包端到端测量
饱和吞吐量>0.3 flit/node/cycle注入率扫描
面积<1mm²综合报告
功耗<100mW功耗仿真
频率>1GHz时序分析

6. 从课程到实践:下一步

完成25课后,你可以朝以下方向发展:

NoC学习路线图 ┌──────────────────────────────────┐ │ 入门(本课程): 25课从零到SoC │ ├──────────────────────────────────┤ │ 进阶: BookSim2仿真 + FPGA验证 │ ├──────────────────────────────────┤ │ 高级: 阅读NOCS/DATE论文 │ ├──────────────────────────────────┤ │ 专家: 设计专用NoC(AI/3D/光电) │ └──────────────────────────────────┘ 推荐阅读: 1. "Principles and Practices of Interconnection Networks" - Dally & Towles 2. "On-Chip Networks: Hardware Design and Design Exploration" - Jerger & Peh 3. NOCS会议论文集(每年最新研究)

7. 毕业项目扩展方向

完成基础NoC SoC后,以下扩展方向可以进一步提升你的设计能力:

7.1 扩展到8×8 Mesh

将4×4扩展到8×8(64个节点)是最自然的扩展。需要解决的问题:

7.2 添加Cache一致性支持

在NoC上实现MESI目录协议:

7.3 性能监控与调试

添加在线性能监控器:

// 性能计数器模块
module perf_counter #(
    parameter NUM_PORTS = 5
)(
    input  logic                  clk, rst_n,
    input  logic [NUM_PORTS-1:0]  port_valid,
    input  logic [NUM_PORTS-1:0]  port_ready,
    input  logic [$clog2(NUM_PORTS)-1:0] route_out,
    // 计数器输出
    output logic [31:0]           total_flits,
    output logic [31:0]           total_stalls,
    output logic [31:0]           port_utilization [0:NUM_PORTS-1]
);
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            total_flits  <= 0;
            total_stalls <= 0;
        end else begin
            for (int p = 0; p < NUM_PORTS; p++) begin
                if (port_valid[p] && port_ready[p])
                    total_flits <= total_flits + 1;
                if (port_valid[p] && !port_ready[p])
                    total_stalls <= total_stalls + 1;
            end
        end
    end
endmodule

💡 毕业项目评估标准

一个优秀的NoC SoC毕业项目应满足:

✅ 功能完整:所有源-目的对通信正确

✅ 性能达标:零负载延迟<15 cycles,饱和吞吐>0.3

✅ 无死锁:72小时测试无死锁

✅ 代码质量:模块化、可参数化、Verilator通过

✅ 文档完整:设计文档+测试报告+性能分析

◀ 上一课 📖 目录 已是最后一课 ▶